/*
 *  AppComponent.cpp
 *  sdaProj
 *
 *  Created by tjmitche on 21/09/2010.
 *  Copyright 2010. All rights reserved.
 *
 */

#include "AppComponent.h"



AppComponent::AppComponent()
{
	AudioFormatManager formatManager;
	formatManager.registerBasicFormats();
	
    fileChooser = new FilenameComponent (T("audiofile "),
										 File::nonexistent,
										 true, false, false,
										 formatManager.getWildcardForAllFormats(),
										 String::empty,
										 T("(choose a WAV or AIFF file)"));
	fileChooser->addListener (this);					
	fileChooser->setBrowseButtonText (T("browse"));	
	addAndMakeVisible (fileChooser);
	
	playButton = new TextButton (T("play"), T("click here to play the current audio file"));
	playButton->addButtonListener (this);
	playButton->setColour (TextButton::buttonColourId, Colours::white);
	playButton->setColour (TextButton::buttonOnColourId, Colours::grey);
	playButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight);
	addAndMakeVisible (playButton);
	
	addAndMakeVisible(recordButton = new TextButton("Record"));
	recordButton->setClickingTogglesState(true);
	recordButton->addButtonListener(this);
	
	addAndMakeVisible(clearButton = new TextButton("Clear"));
	clearButton->addButtonListener(this);
	
	addAndMakeVisible(saveButton = new TextButton("Save"));
	saveButton->addButtonListener(this);
	
	buffer = 0;
	playPosition = 0;	
	recordOn = false;
	
	// and initialise the device manager with no settings so that it picks a
	// default device to use.
	const String error (audioDeviceManager.initialise (1, /* number of input channels */
													   2, /* number of output channels */
													   0, /* no XML settings.. */
													   true  /* select default device on failure */));
	if (error.isNotEmpty())
	{
		AlertWindow::showMessageBox (AlertWindow::WarningIcon,
									 T(PROJECT_NAME),
									 T("Couldn't open an output device!\n\n") + error);
	}
	else
	{
		// start the IO device pulling its data from our callback..
		audioDeviceManager.addAudioCallback (this);
	}
}

AppComponent::~AppComponent()
{
	audioDeviceManager.removeAudioCallback (this);//unregister the audio callback
	deleteAndZero (buffer);
	deleteAllChildren(); //deletes all added components
}


//==============================================================================
void AppComponent::resized()
{
	playButton->setBounds (5, 10, 50, 20);
	fileChooser->setBounds (getWidth()-210, 10, 200, 20);
	recordButton->setBounds(10, getHeight()/2-30, getWidth()/3-20, 20);
	clearButton->setBounds(getWidth()/3, getHeight()/2-30, getWidth()/3-20, 20);
	saveButton->setBounds(getWidth()/3*2, getHeight()/2-30, getWidth()/3-20, 20);
}

//==============================================================================
void AppComponent::filenameComponentChanged (FilenameComponent* filenameComponent)
{
	// this is called when the user changes the filename in the file chooser box
	File audioFile (filenameComponent->getCurrentFile().getFullPathName());
	
	if(audioFile.existsAsFile())
	{
		// create a new file source from the file..
		// get a format manager and set it up with the basic types (wav, ogg and aiff).
		AudioFormatManager formatManager;
		formatManager.registerBasicFormats();
		AudioFormatReader* reader = formatManager.createReaderFor(audioFile);
		
		if (reader != 0)
		{
			AudioSampleBuffer *tempbuf = new AudioSampleBuffer(reader->numChannels, reader->lengthInSamples);
			tempbuf->readFromAudioReader(reader, 0, reader->lengthInSamples, 0, true, true);
			
			sharedMemory.enter();
			deleteAndZero (buffer);
			playPosition = 0;
			buffer = tempbuf;
			sharedMemory.exit();
		}
	}
	else
	{		

		AlertWindow::showMessageBox (AlertWindow::WarningIcon,
									 T(PROJECT_NAME),
									 T("Couldn't open file!\n\n"));
	}	
}

void AppComponent::buttonClicked (Button* button)
{
    if (button == playButton && buffer != 0)
	{
		playPosition = 0;
	}
	else if(button == recordButton)
	{
		if (recordButton->getToggleState()) 
		{
			recordOn = true;
		}
		else
		{
			recordOn = false;
		}
	}
	else if(button == clearButton)
	{
		buffer->clear();
		playPosition = 0;
	}
	else if(button == saveButton)
	{
		File file = File::getSpecialLocation (File::userDesktopDirectory).getNonexistentChildFile ("AudioRecording", ".wav");
		OutputStream* outStream = file.createOutputStream();
		WavAudioFormat wavFormat;
		AudioFormatWriter* writer = wavFormat.createWriterFor (outStream, 44100, 1, 16, NULL, 0);
		buffer->writeToAudioWriter(writer, 0, buffer->getNumSamples());
		delete writer;
	}
}

	

//==============================================================================
//Audio Callbacks
//==============================================================================
void AppComponent::audioDeviceIOCallback (const float** inputChannelData,
										   int totalNumInputChannels,
										   float** outputChannelData,
										   int totalNumOutputChannels,
										   int numSamples)
{
	
	
	const float *inL; //presume only mono input
	float *outL, *outR; 
	float *data;
	
	inL = inputChannelData[0];
	outL = outputChannelData[0];
	outR = outputChannelData[1];
	
	sharedMemory.enter();
	while(numSamples--)
	{
		if (buffer) 
		{
			data = buffer->getSampleData(0, playPosition);
			if(recordOn == true)
			{
				*data += *inL;
			}
			*outL = *data; 
			*outR = *data;
			playPosition++;
			if((playPosition == buffer->getNumSamples())) //loop
			{
				playPosition = 0;
			}
		}
		inL++; 
		outL++;
		outR++;
	}
	sharedMemory.exit();
	 
}

void AppComponent::audioDeviceAboutToStart (AudioIODevice* device)
{
	
}

void AppComponent::audioDeviceStopped()
{
	
}

